<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<script>
    /*
    * 箭头函数的this
    *   和普通函数的this不一样，箭头函数的this 会强行绑定到上下文中
    *   上下文的this是什么，箭头函数里面的this就是什么
    *   找上下文小技巧：看包裹着箭头函数的那个函数被谁调用 它的this指向就是箭头函数的上下文
    *
    *   什么叫做上下文？
    *   父级作用域
    *   就是这个函数声明位置的上一行和下一行
    *
    *
    *
    * */



    /*上下文是window的情况：

    //这个箭头函数是直接在全局当中声明的，所以它的上下文就是全局window，所以这个箭头函数的this会永远绑定到window，后续无论这个函数被谁调用，都不会改变this指向
    let foo = () => {
        console.log(this)
    }

    let obj = {
        foo:foo,
    }

    foo()

    obj.foo()

    //在它的上文中打印this
    console.log(this)
    let obj = {
        foo:() => {
            console.log(this)
        }
    }
    foo()
    obj.foo()
    //上下文是指这个foo函数所出现的运行环境是全局还是函数 因为这个函数是用对象包裹的 而不是用函数包裹的 对象并不会影响this指向 只有在被其他函数包裹的时候才有可能改变

     */

    /*let obj = {
        fn:function (){
            //console.log(this) //这里就是箭头函数的上文 而这里的this是obj
            let foo = () => {
                console.log(this)
            }
            foo() //箭头函数执行
        }
    }

    obj.fn() //确定箭头函数的上下文 即确定是谁在调用这个箭头函数的父级函数 这里是obj在调用 所以它的this就是父级函数的this即obj 所以它的this指向就是obj

    let f = obj.fn
    f() //此时这个函数执行 这个函数是window调用的 所以这个函数的this指向window 又因为箭头函数this指向是父级作用域的this指向 此时箭头函数的上下文就是window 所以箭头函数的this指向也是window
    */


    let obj = {
        fn:function (){
            let foo = () =>{ //声明了一个箭头函数
                console.log(this)
            }
            return foo //将这个声明的箭头函数返回出来
        }
    }

    let f = obj.fn() //注意这里的括号是调用执行了函数
    //obj.fn执行之后的返回内容传递给f 在这一行代码之前 箭头函数foo并不存在 因为箭头函数是在函数fn执行之后才声明出来的 obj.fn() 所以函数fn它的调用者就是obj
    //所以函数fn的this指向obj 而箭头函数在函数fn之中 根据箭头函数在声明时会强行绑定到上下文 所以箭头函数的this指向obj

    f() //f执行

    //题目1
    let obj = {
        fn:function (){
            let foo = () => {
                console.log(this)
            }
            foo()
        }
    }

    let f = obj.fn //将函数function赋值给了f
    obj.fn() //obj.fn()它的调用者就是函数前面的obj 所以this指向obj
    f()   //就相当于是function函数执行 而这里没有调用者 所以是window调用的 而箭头函数声明时强行绑定上下文 外面函数是window调用 那里面箭头函数的上下文就是window


    //题目2
    let obj = {
        fn:function (){
            let foo = () => {
                console.log(this)
            }
            return foo
        }
    }

    let f = obj.fn() //此时才真正生成了箭头函数foo 所以此时箭头函数声明强行绑定上下文 就绑定到了函数function中的this 而函数function是由obj调用的
    //所以函数function的this指向obj 受到函数function的影响 其内部箭头函数this也绑定到上下文中（上下文可以理解为大函数所包裹的位置）也就绑定到obj
    //所以箭头函数的this指向就是obj
    f() //这里f执行就是箭头函数执行 箭头函数执行要看它声明的时候被绑定的上下文 而不是像普通函数一样看谁调用了它 这里箭头函数this指向obj


    //题目3
    let obj = {
        fn:function (){
            let foo = () => {
                console.log(this)
            }
            return foo
        }
    }

    let f = obj.fn
    f()() //这里f()就相当于函数function执行，这个函数执行之后有个返回值箭头函数foo f()()就表示作为返回值的箭头函数foo再执行 找箭头函数的this上下文可以看作找包裹箭头函数的那个大函数的this指向
    //箭头函数是 在130行 的 f()()被调用下生成的 这里函数function的调用者是window(因为找不到就是window) 而箭头函数this所绑定的上下文就是函数function的this指向
    //所以箭头函数的this也指向window


    //题目4
    function foo(){
        let fn = () => {
            console.log(this)
        }
        function foo(f){
            f()
        }
        return{
            fn:fn,
            foo:foo
        }
    }

    let s = foo() //s是函数foo的执行结果 foo执行结果就是 return出来的对象 所以s就是那个被return的对象
    s.foo(s.fn) //s.foo会从里面的作用域开始找foo 里面的foo就做了一件事 将传进来的参数执行 里面的参数是s.fn fn就是那个箭头函数 所以这一句代码就是箭头函数执行
    //箭头函数的上下文就是整个包裹它的大函数 整个大函数是怎么执行的 由150行可知 foo()被浏览器调用 所以大函数this指向浏览器window 所以箭头函数的this上下文就是window
    //所以箭头函数this指向就是window





</script>
</body>
</html>